package com.autumn.word.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import com.autumn.util.ExceptionUtils;
import com.autumn.word.EvaluateOptions;
import com.autumn.word.Token;
import com.autumn.word.WordSession;
import com.autumn.word.WorkEvaluateWithOptional;
import com.autumn.word.WorkEvaluateWithOptionalTarget;
import com.autumn.word.WorkWithOptional;
import com.autumn.word.pdf.PdfConverter;
import com.autumn.word.pdf.PdfProperties;

/**
 * 
 * @author 老码农 2019-04-24 01:41:50
 */
class WorkWithOptionalImpl implements WorkWithOptional {

	private PdfConverter pdfConverter;
	private InputStream inputStream;
	private XWPFDocument document;
	private boolean closeStream;

	/**
	 * document
	 * 
	 * @param pdfConverter
	 * @param inputStream
	 * @param document
	 * @param closeStream
	 */
	public WorkWithOptionalImpl(PdfConverter pdfConverter, InputStream inputStream, XWPFDocument document,
			boolean closeStream) {
		this.pdfConverter = pdfConverter;
		this.inputStream = inputStream;
		this.document = document;
		this.closeStream = closeStream;

	}

	@Override
	public WorkEvaluateWithOptional evaluate(Object obj) throws IOException {
		return this.evaluate(obj, EvaluateOptions.DEFAULT);
	}

	@Override
	public WorkEvaluateWithOptional evaluate(Object obj, EvaluateOptions options) throws IOException {
		return this.evaluate(obj, Token.DEFAULT, options);
	}

	@Override
	public WorkEvaluateWithOptional evaluate(Object obj, Token token, EvaluateOptions options) throws IOException {
		try {
			if (this.document == null) {
				this.document = new XWPFDocument(this.inputStream);
			}
			WordSession session = new WordSession(obj, token);
			this.document = session.evaluate(this.document, options);
			return new WorkEvaluateWithOptionalImpl(this.document, this.pdfConverter);
		} finally {
			if (closeStream) {
				IOUtils.closeQuietly(this.inputStream);
			}
		}
	}

	@Override
	public WorkEvaluateWithOptionalTarget toPdf() {
		return toPdf(PdfProperties.DEFAULT);
	}

	@Override
	public WorkEvaluateWithOptionalTarget toPdf(PdfProperties pdfProperties) {
		if (this.document != null) {
			ByteArrayOutputStream docOutput = new ByteArrayOutputStream();
			try {
				document.write(docOutput);
				this.inputStream = new ByteArrayInputStream(docOutput.toByteArray());
			} catch (IOException e) {
				ExceptionUtils.throwValidationException(e.getMessage());
			} finally {
				IOUtils.closeQuietly(docOutput);
			}
		}
		return new WorkEvaluateWithOptionalTargetImpl(
				new PdfOptionalTargetFormat(this.inputStream, this.closeStream, this.pdfConverter, pdfProperties));
	}

}
